/*
 * ODO: Real-Time In-Memory ORM/DBMS Grid software
 * Copyright (c) 2008, Michael Oksenenko
 * All rights reserved.
 */
//----------------------------------------------------------------------------
#include "OsConfig.hpp"
#if ODO_OS_VISTA == ODO_CHOSEN_OS
//----------------------------------------------------------------------------
#include "RegeditVista.hpp"

#include "OsComponentFactory.hpp"
#include "windows.h"
#include <string>
#include <iostream>

using namespace odo;

void RegeditVista::openKey(const wchar_t* aKey) {
	if (isOpenKey()) closeKey();
	unsigned long retCode = static_cast<unsigned long>(
		RegCreateKeyExW(
			HKEY_LOCAL_MACHINE,			// handle to an open registry key
			static_cast<LPCTSTR>(aKey),	// name of a subkey
			0,							// reserved and must be zero
			0,							// user-defined class type of this key
			REG_OPTION_NON_VOLATILE,	// options
			KEY_READ | KEY_WRITE |
			KEY_QUERY_VALUE,			// access rights for the key
			0,							// default security descriptor
			&mKeyHandle,				// receives a handle to the key
			0							// receives: new key or existed
		)
	);
	if (ERROR_SUCCESS != retCode) {
		OsComponentFactory::getError()->printLast(retCode);
		std::wcerr << L"FAIL create/open key: " << aKey << std::endl;
	}
}

void RegeditVista::closeKey() {
	if (isClosedKey()) return;
	unsigned long retCode = static_cast<unsigned long>(
		RegCloseKey(
			mKeyHandle	// handle to the open key
		)
	);
	if (ERROR_SUCCESS != retCode) {
		OsComponentFactory::getError()->printLast(retCode);
		std::wcerr << L"FAIL close key." << std::endl;
	}
	mKeyHandle = 0;
}

bool RegeditVista::isOpenKey() {
	return (0 != mKeyHandle);
}

bool RegeditVista::isClosedKey() {
	return (0 == mKeyHandle);
}

void RegeditVista::setValue(const wchar_t* aValueName, const wchar_t* aValue) {
	if (isClosedKey()) {
		std::wcerr << L"FAIL set value on closed key: "
			<< aValueName << "/" << aValue << std::endl;
		return;
	}
	size_t valueSizeWithZero = (1 + wcslen(aValue)) * sizeof(wchar_t);
	unsigned long retCode = static_cast<unsigned long>(
		RegSetValueExW(
			mKeyHandle,				// handle to an open registry key
			static_cast<LPCTSTR>(aValueName), // name of the value to be set
			0,						// reserved and must be zero
			REG_SZ,					// type of data pointed by the data parameter
			(LPBYTE)aValue,			// data to be stored
			static_cast<DWORD>(valueSizeWithZero) // data parameter size (with zero)
		)
	);
	if (ERROR_SUCCESS != retCode) {
		OsComponentFactory::getError()->printLast(retCode);
		std::wcerr << L"FAIL set value: "
			<< aValueName << "/" << aValue << std::endl;
	}
}

std::wstring RegeditVista::getValue(const wchar_t* aValueName) {
	if (isClosedKey()) {
		std::wcerr << L"FAIL get value on closed key: "
			<< aValueName << std::endl;
		return std::wstring(L"");
	}
	const size_t VALUE_MAX_SIZE =
		static_cast<size_t>(STRING_BUFFER_SIZE) * sizeof(wchar_t);
	wchar_t valueBuffer[sizeof(wchar_t) + VALUE_MAX_SIZE];
	DWORD sizeOfData = VALUE_MAX_SIZE;
	DWORD typeOfData;
	unsigned long retCode = static_cast<unsigned long>(
		RegGetValueW(
			mKeyHandle,			// handle to an open registry key
			0,					// optional subkey
			aValueName,			// name of the registry value
			RRF_RT_REG_SZ,		// restrict the data type of value
			&typeOfData,		// receives type code of data parameter
			(PVOID)valueBuffer,	// receives the value's data
			&sizeOfData			// specifies the size of the data buffer 
		)
	);
	valueBuffer[VALUE_MAX_SIZE] = L'\0'; // guard
	if (ERROR_SUCCESS != retCode) {
		OsComponentFactory::getError()->printLast(retCode);
		std::wcerr << L"FAIL get value: " << aValueName << std::endl;
		if (ERROR_MORE_DATA == retCode) {
			std::wcerr << L"FAIL get value; small buffer size (current/need: "
				<< VALUE_MAX_SIZE << "/" << sizeOfData << ")" << std::endl;
		}
		return std::wstring(L"");
	}
	if (REG_SZ != typeOfData) {
		std::wcerr << L"FAIL get value; wrong data type (value/type/ret_type: "
			<< aValueName
			<< "/" << REG_SZ
			<< "/" << typeOfData
			<< ")" << std::endl;
		return std::wstring(L"");
	}
	return std::wstring(valueBuffer);
}

RegeditVista::~RegeditVista() {
	closeKey();
}

RegeditVista::RegeditVista() {
	mKeyHandle = 0;
}
//----------------------------------------------------------------------------
#endif /* ODO_OS_VISTA */
//----------------------------------------------------------------------------
